<template>
  <section class="jee-image-upload-container">
    <!-- 上传区 -->
    <div class="upload-wrap" :class="{ 'single-mode': file.imageUrl }">
      <el-upload
        ref="upload"
        class="z-image-uploader jee-hover-border"
        action=""
        :accept="getAccept"
        :show-file-list="false"
        :before-upload="beforeImageUpload"
        :on-change="handleChange"
        :auto-upload="false"
      >
        <div class="text-wrap">
          <i :icon="icon"></i>
          <div class="text" v-if="title">{{ title }}</div>
          <div class="text" v-if="getImageSize">{{ getImageSize }}</div>
        </div>
      </el-upload>
      <!-- 上传后的样式 -->
      <div class="image-wrap" v-if="file.imageUrl">
        <div class="image">
          <img
            :src="file.imageUrl"
            :style="{ width: width || 'auto', height: height || 'auto' }"
          />
        </div>
        <div class="img-editor-wrap">
          <i class="el-icon-close" @click="handleRemove"></i>
          <div class="editor jee-hover-border-important">
            <el-tooltip content="重新上传" placement="bottom" effect="light">
              <i class="el-icon-refresh" @click="reUpload"></i>
            </el-tooltip>
            <el-tooltip content="查看大图" placement="bottom" effect="light">
              <i class="el-icon-search" @click="handlePreview"></i>
            </el-tooltip>
            <el-tooltip content="裁剪" placement="bottom" effect="light">
              <i class="el-icon-crop" @click="handleCropper"></i>
            </el-tooltip>
          </div>
        </div>
      </div>
    </div>
    <!-- 进度条 -->
    <!-- <el-progress :stroke-width='6' :percentage="percentage" v-if="percentage>0 && percentage <=100" style="maxWidth: 414px;"></el-progress> -->
    <!-- 说明文字 -->
    <div class="z-tip-form-item" v-if="tip">{{ tip }}</div>
    <!-- 放大 -->
    <el-dialog
      :visible.sync="dialogVisible"
      custom-class="transparent"
      class="image-preview-dialog"
      :close-on-click-modal="false"
      append-to-body
      :width="imageStyle.w + 60 + 'px'"
    >
      <img class="t-img" :src="file.imageUrl" alt="" />
    </el-dialog>
    <!-- <el-dialog
      class="image-preview-dialog"
      :visible.sync="dialogVisible"
      :close-on-click-modal="false"
      :fullscreen='true'
      append-to-body
      :width="imageStyle.width"
    >
      <el-image
        :style="imageStyle"
        :src="file.imageUrl"
        fit="contain">
          <div slot="error" class="image-slot">
            <i class="el-icon-picture-outline"></i>
          </div>
      </el-image>
    </el-dialog> -->
    <!-- 裁剪 -->
    <el-dialog
      class="cropper-dialog"
      title="图片裁剪"
      :visible.sync="dialogVisible2"
      append-to-body
    >
      <div class="cropper-content">
        <div class="cropper-wrap">
          <vueCropper
            ref="cropper"
            :img="file.imageUrl"
            :info="option.info"
            :full="option.full"
            :outputSize="option.outputSize"
            :outputType="option.outputType"
            :canMove="option.canMove"
            :canMoveBox="option.canMoveBox"
            :centerBox="option.centerBox"
            :fixedBox="option.fixedBox"
            :fixed="option.fixed"
            :original="option.original"
            :autoCrop="option.autoCrop"
            :autoCropWidth="option.autoCropWidth"
            :autoCropHeight="option.autoCropHeight"
            :high="option.high"
            @realTime="realTime"
          />
        </div>
        <div
          class="show-preview"
          :style="{ width: previews.w + 'px', height: previews.h + 'px' }"
        >
          <div :style="previews.div">
            <img :src="previews.url" :style="previews.img" />
          </div>
        </div>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button size="small" @click="dialogVisible2 = false"
          >取 消</el-button
        >
        <el-button
          size="small"
          type="primary"
          @click="handleSubmit"
          :loading="loading"
          >确认</el-button
        >
      </div>
    </el-dialog>
  </section>
</template>
<script>
import { VueCropper } from "vue-cropper";
import { getImgToBase64 } from "@/utils";

export default {
  name: "JeeImageUpload",
  props: {
    value: {
      validator() {
        return true;
      },
    },
    imgType: {
      type: String,
      default: "",
    },
    autoUpload: {
      type: Boolean,
      default: true,
    },
    desc: {
      type: String,
      default: "",
    },
    tip: {
      type: String,
      default: "",
    },
    title: {
      type: String,
      default: "点击上传图片",
    },
    iconClass: {
      type: String,
      default: "shangchuantupian",
    },
    width: {
      type: [Number, String],
      default: 0,
    },
    height: {
      type: [Number, String],
      default: 0,
    },
    type: {
      type: [Array, String],
      default: () => [],
    },
    size: {
      type: [String, Number],
      default: "",
    },
    unit: {
      type: String,
      default: "",
    },
    defaultFileName: {
      type: String,
      default: "",
    },
    defaultUrl: {
      type: String,
      default: "",
    },
    limit: {
      type: [String, Number],
      default: "",
    },
  },
  components: {
    VueCropper,
  },
  data() {
    return {
      dialogVisible: false,
      dialogVisible2: false,
      loading: false,
      file: {},
      option: {
        autoCropWidth: this.width || 100,
        autoCropHeight: this.height || 100,
        info: true, // 裁剪框的大小信息
        outputSize: 1, // 裁剪生成图片的质量
        outputType: "jpeg", // 输出图片格式
        canScale: true, // 图片是否允许滚轮缩放
        autoCrop: true, // 是否默认生成截图框
        fixedBox: false, // 固定截图框大小 不允许改变
        fixed: false, // 是否开启截图框宽高固定比例
        full: false, // 是否输出原图比例的截图
        canMove: true, // 能否拖动图片
        canMoveBox: true, // 截图框能否拖动
        original: false, // 上传图片按照原始比例渲染
        centerBox: false, // 截图框是否被限制在图片里面
        high: true, // 是否根据dpr生成适合屏幕的高清图片
      },
      previews: {},
      percentage: 0,
      imageStyle: {},
    };
  },
  computed: {
    getImageDesc() {
      if (this.desc) return this.desc;
      const allowType =
        this.type instanceof Array ? this.type.join(", ") : this.type;
      let desc = allowType ? `支持 ${allowType} 图片格式` : "";
      if (this.size && this.unit)
        desc = desc + ` (文件大小不超过${this.size}${this.unit})`;
      return desc;
    },
    getImageSize() {
      return this.width && this.height
        ? `建议${this.width} * ${this.height}PX`
        : "";
    },
    getAccept() {
      const allowTypes =
        this.type instanceof Array
          ? this.type
          : this.type
          ? this.type.split(",")
          : [];
      return allowTypes.length
        ? allowTypes.map((t) => `image/${t}`).join(",")
        : "image/*";
    },
  },
  watch: {
    value(newVal) {
      if (!newVal) {
        this.file = {};
      }
      if (typeof newVal === "object") {
        this.initData();
      }
    },
    defaultUrl(newVal, oldVal) {
      if (newVal !== oldVal) {
        this.initData();
      }
    },
  },
  methods: {
    // 获取图片宽高
    getImageStyle() {
      const url = this.file.imageUrl;
      if (url) {
        const that = this;
        var img = new Image();
        img.src = url;
        img.onload = function () {
          that.imageStyle = {
            width: img.width + "px",
            height: img.height + "px",
            w: img.width,
            h: img.height,
          };
        };
      }
    },
    // 点击放大查看
    handlePreview() {
      this.dialogVisible = true;
    },
    // 点击裁剪
    handleCropper() {
      this.dialogVisible2 = true;
    },
    // 重新上传
    reUpload() {
      this.$refs.upload.$refs["upload-inner"].$refs.input.click();
      // document.querySelector('.jee-image-upload-container .el-upload input').click()
    },
    // 上传-文件类型
    uploadType(file) {
      var type = file.raw.type;
      var i = type.indexOf("/");
      var suffix = type.slice(0, i);
      var fileType = "";
      // File文件 Flash Flash Image图片 Media视频 Audio音频 为空则默认Image
      switch (suffix) {
        case "image":
          fileType = "";
          break;
        case "text":
          fileType = "File";
          break;
        case "application":
          fileType = "File";
          break;
        case "video":
          fileType = "Media";
          break;
        case "audio":
          fileType = "Audio";
          break;
        default:
          fileType = "";
          break;
      }
      return fileType;
    },
    // 上传-选择文件
    handleChange(file) {
      if (!this.beforeImageUpload(file)) return;
      this.file = {
        file: file,
        fileName: this.defaultFileName || file.name,
        fileType: this.uploadType(file),
        imageUrl: URL.createObjectURL(file.raw),
      };
      this.getImageStyle();
      this.handleUpload();
    },
    // 上传到服务器
    handleUpload() {
      const param = new FormData(); // 创建form对象
      param.append("uploadFile", this.file.file.raw, this.file.fileName); // 通过append向form对象添加数据
      if (this.autoUpload) {
        // param.append('spaceId', this.id)
        param.append("typeStr", this.file.fileType);
        param.append("addToRes", true);
        const that = this;
        const onUploadProgress = function (e) {
          // 属性lengthComputable主要表明总共需要完成的工作量和已经完成的工作是否可以被测量
          // 如果lengthComputable为false，就获取不到e.total和e.loaded
          if (e.lengthComputable) {
            var rate = e.loaded / e.total; // 已上传的比例
            if (rate < 1) {
              that.percentage = Number((rate * 100).toFixed(0));
              // 这里的进度只能表明文件已经上传到后台，但是后台有没有处理完还不知道
              // 因此不能直接显示为100%，不然用户会误以为已经上传完毕，关掉浏览器的话就可能导致上传失败
            } else {
              that.percentage = 100;
            }
          }
        };
        this.$request.fetchUpload(param, onUploadProgress).then((res) => {
          if (res.code === 200) {
            this.$message({
              message: "上传成功",
              type: "success",
            });
            this.$emit("input", res.data.resourceId);
            this.$emit("getUrl", res.data, this.imgType);
          } else {
            this.handleRemove();
          }
          this.percentage = 0;
        });
      } else {
        this.$emit("input", param);
        this.$emit("getUrl", this.file, this.imgType);
      }
    },
    // 移除
    handleRemove() {
      this.$emit("input", "");
      this.file = {};
      this.$emit("getUrl", {}, this.imgType);
    },
    // 上传到页面前进行检查
    beforeImageUpload(file) {
      // 判断文件类型 windows下accept无效
      let isJPG = true;
      var i = file.name.lastIndexOf(".");
      var suffix = file.name.substring(i + 1);

      const allowTypes =
        this.type instanceof Array
          ? this.type
          : this.type
          ? this.type.split(",")
          : [];

      if (allowTypes.length) {
        isJPG = allowTypes.includes(suffix);
      }
      // 判断文件大小
      let isLt2M = true;
      if (this.size) {
        const allowSize = this.unit === "MB" ? 1024 * 1024 : 1024;
        isLt2M = file.size / allowSize < Number(this.size);
      }
      // 提示错误信息
      if (!isJPG) {
        this.$message.error(`上传图片只能是 ${allowTypes.join(",")} 格式!`);
      }
      if (!isLt2M) {
        this.$message.error(
          `上传图片大小不能超过 ${this.size}${this.unit || "KB"}!`
        );
      }
      return isJPG && isLt2M;
    },
    // 实时预览函数
    realTime(data) {
      this.previews = data;
    },
    // 获取截图数据
    handleSubmit() {
      this.$refs.cropper.getCropBlob((data) => {
        let files = new File([data], this.file.fileName, {
          type: "image/png",
          lastModified: Date.now(),
        });
        this.file.file = { raw: files };
        this.file.imageUrl = URL.createObjectURL(data);
        this.dialogVisible2 = false;
        this.handleUpload();
      });
    },
    initData() {
      if (!this.autoUpload) {
        return;
      }
      // 传单图路径，转为图片数据
      const that = this;
      const getDefaultFile = function (dataUrl) {
        that.$set(that.file, "imageUrl", dataUrl);
      };
      if (this.defaultUrl) {
        getImgToBase64(this.$getPath(this.defaultUrl), getDefaultFile);
      } else {
        this.file = {};
      }
      // 传单图对象，返回id
      if (this.value && typeof this.value === "object") {
        this.$emit("input", this.value.id || "");
      }
    },
  },
  mounted() {
    this.initData();
  },
};
</script>
<style lang="scss">
.jee-image-upload-container {
  .desc {
    color: #b3b3b3;
    font-size: 12px;
    line-height: 1.5;
    padding-top: 11px;
    padding-bottom: 17px;
  }
  .upload-wrap {
    width: 140px;
    display: flex;
    flex-wrap: wrap;
    .image-wrap {
      position: relative;
      margin-left: 20px;
      margin-bottom: 20px;
      .img-editor-wrap {
        position: absolute;
        top: 0;
        left: 0;
        width: 140px;
        height: 140px;
        background-color: rgba(0, 0, 0, 0.7);
        border-radius: 4px;
        opacity: 0;
        &:hover {
          opacity: 1;
        }
        .guanbi {
          position: absolute;
          top: 8px;
          right: 8px;
          font-size: 18px;
          fill: #ffffff;
        }
        .editor {
          display: flex;
          justify-content: space-between;
          align-items: center;
          width: 140px;
          height: 40px;
          position: absolute;
          bottom: 0;
          padding: 0 16px;
          box-sizing: border-box;
          background-color: #ffffff;
          border-radius: 0 0 4px 4px;
          border: 1px dashed #e2e2e2;
          .jee-svg-icon {
            font-size: 22px;
            fill: #b3b3b3;
            cursor: pointer;
          }
        }
      }
      .image {
        width: 140px;
        height: 140px;
        background-color: #f0f0f0;
        display: flex;
        align-items: center;
        border-radius: 4px;
        img {
          max-width: 138px;
          max-height: 138px;
          display: block;
          margin: 0 auto;
        }
      }
    }
    &.single-mode {
      .z-image-uploader {
        visibility: hidden;
        position: absolute;
      }
      .image-wrap {
        margin: 0;
      }
    }
  }
}
.transparent {
  background: transparent;
  box-shadow: none !important;
  padding: 52px 0;
}
.el-dialog {
  .el-dialog__body {
    .cropper-dialog {
      .cropper-content {
        .cropper-wrap {
          width: 100%;
          height: 300px;
        }
        .show-preview {
          border: 1px solid #e8e8e8;
          margin-top: 20px;
          overflow: hidden;
        }
      }
    }
  }
}
</style>
